package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os/exec"
	"sync"
	"syscall"

	"github.com/shuzr/zlog"
	"github.com/tidwall/gjson"
)

// HttpFpeg ...
type HttpFpeg struct {
	worker *sync.Map
}

// NewHttpFpeg ...
func NewHttpFpeg() *HttpFpeg {
	return &HttpFpeg{worker: &sync.Map{}}
}

func (h *HttpFpeg) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintln(w, err)
		return
	}
	switch r.URL.Path {
	case "/start":
		h.fpegStart(w, body)
	case "/stop":
		h.fpegStop(w, body)
	case "/count":
		h.fpegCount(w)
	default:
		w.WriteHeader(http.StatusNotFound) // 404
		fmt.Fprintf(w, "no such path: %s", r.URL)
	}
}

func (h *HttpFpeg) fpegStart(w http.ResponseWriter, b []byte) {

	jarray := gjson.GetManyBytes(b, "id", "url", "name")
	cmdStr := fmt.Sprintf("ffmpeg -re -stream_loop -1 -i \"%s\" -vcodec copy -acodec copy -f flv \"%s\"", jarray[2].String(), jarray[1].String())
	zlog.Info(cmdStr)
	cmd := exec.Command("/bin/sh", "-c", cmdStr)
	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	if err := cmd.Start(); err != nil {
		fmt.Fprintln(w, err.Error())
		return
	}

	id := jarray[0].String()
	h.worker.Store(id, cmd)
	fmt.Fprintln(w, "start worker:", id)
}

func (h *HttpFpeg) fpegStop(w http.ResponseWriter, b []byte) {
	id := gjson.GetBytes(b, "id").String()
	if v, o := h.worker.Load(id); o {
		err := syscall.Kill(-v.(*exec.Cmd).Process.Pid, syscall.SIGKILL)
		if err != nil {
			fmt.Fprintln(w, err)
		} else {
			h.worker.Delete(id)
			fmt.Fprintln(w, "stop worker:", id)
		}
	}
}

func (h *HttpFpeg) fpegCount(w http.ResponseWriter) {
	ids := []string{}
	h.worker.Range(func(k, v interface{}) bool {
		if id, ok := k.(string); ok {
			ids = append(ids, id)
		}
		return true
	})
	jd, _ := json.Marshal(ids)
	w.Write(jd)
}

func main() {
	http.ListenAndServe(":16373", NewHttpFpeg())
}
